package com.lz.sports.vm

import android.text.TextUtils
import android.widget.Toast
import androidx.lifecycle.LifecycleOwner
import androidx.lifecycle.MutableLiveData
import com.lz.comm.SP
import com.lz.comm.extension.toJsonRequestBody
import com.lz.comm.net.HttpManager
import com.lz.library.base.BaseApp
import com.lz.library.base.BaseModel
import com.lz.library.base.BaseViewModel
import com.lz.library.extension.showToast
import com.lz.library.utils.FileUtils
import com.lz.sports.LogUtils
import com.lz.sports.R
import com.lz.sports.api.DownloadApi
import com.lz.sports.api.UploadApi
import com.lz.sports.bean.CommonModel
import com.lz.sports.bean.ZipAddress
import com.lz.sports.core.*
import com.lz.sports.utils.DateUtils
import com.lz.sports.utils.ToastUtils
import com.lz.sports.utils.toArrayList
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.flow.*
import kotlinx.coroutines.withContext
import okhttp3.MediaType
import okhttp3.MultipartBody
import okhttp3.RequestBody
import java.io.File

class SysSettingViewModel : BaseViewModel<BaseModel>() {

    /* ------------------- 服务器配置 ------------------- */
    val serverAddress = MutableLiveData<String>()

    //计划编号, 考区编号, 考点
    val examPlanId = MutableLiveData<String>()
    val examAreaId = MutableLiveData<String>()
    val examRoomId = MutableLiveData<String>()

    //上传模式
    val uploadModels by lazy { R.array.sysUploadModel.toArrayList() }
    var modelPosition = 0
    val uploadModel = MutableLiveData<String>()

    /* ------------------- 本机信息配置 ------------------- */
    //是否为主机
    val isSuper = MutableLiveData<Boolean>()

    //设备名
    val deviceNum = MutableLiveData<String>()

    //波特率
    val baudStr = MutableLiveData<String>()

    //检录功能
    val hasCheckIn = MutableLiveData<Boolean>()

    //签到功能
    val hasSignIn = MutableLiveData<Boolean>()

    //成绩确认功能
    val hasResultConfirm = MutableLiveData<Boolean>()

    //数据查询功能
    val hasDataSelect = MutableLiveData<Boolean>()

    /* ------------------- 考生配置 ------------------- */
    val inspectModel = MutableLiveData<CommonModel>()
    val signInModel = MutableLiveData<CommonModel>()
    val queryModel = MutableLiveData<CommonModel>()
    val sureModel = MutableLiveData<CommonModel>()

    /* ------------------- 打印机配置 ------------------- */
    val hasPrinterAuto = MutableLiveData<Boolean>()

    /* ------------------- 音响配置 ------------------- */
    val soundChannelStr = MutableLiveData<String>()
    private var soundChannel = 0
    val soundPre = MutableLiveData<Boolean>()
    val soundStart = MutableLiveData<Boolean>()
    val soundEnd = MutableLiveData<Boolean>()

    //音量
    val soundVolume = MutableLiveData<Int>()

    //自动播报节点
    val soundAuto = MutableLiveData<Boolean>()

    /* ------------------- 其他配置 ------------------- */
    //是否允许新增学生
    val studentAddAuto = MutableLiveData<Boolean>()

    override fun onCreate(owner: LifecycleOwner) {
        launch {
            updateDialogLoading(true)
            withContext(Dispatchers.IO) {
                //服务器配置
                serverAddress.postValue(SP.getString(K_SERVER_ADDRESS, v_server_address))
                examPlanId.postValue(ProjectManager.examPlan?.planCode)
                examAreaId.postValue(ProjectManager.currentExamArea?.examAreaCode)
                examRoomId.postValue(ProjectManager.currentExamSite?.examSiteCode)
                modelPosition = SP.getInt(K_UPLOAD_MODEL, v_upload_model)
                uploadModel.postValue(uploadModels.getOrNull(modelPosition))

                //主机名, 与辅助机相关属性
                isSuper.postValue(SP.getBoolean(K_IS_SUPER_MANAGER, v_isSuperManager))
                deviceNum.postValue(SP.getString(K_DEVICE_NAME, v_deviceName))
                baudStr.postValue("${SP.getInt(K_DEVICE_BAUD, v_deviceBaud)}")
                hasCheckIn.postValue(SP.getBoolean(K_MODULE_CHECK_IN, v_moduleCheckIn))
                hasSignIn.postValue(SP.getBoolean(K_MODULE_SIGN_IN, v_moduleSignIn))
                hasResultConfirm.postValue(SP.getBoolean(K_MODULE_RESULT_CONFIRM, v_moduleResultConfirm))
                hasDataSelect.postValue(SP.getBoolean(K_MODULE_DATA_SELECT, v_moduleDataSelect))

                //初始化本机信息与成绩配置
                inspectModel.postValue(VerifyManager.inspectModel())
                signInModel.postValue(VerifyManager.signInModel())
                queryModel.postValue(VerifyManager.queryModel())
                sureModel.postValue(VerifyManager.sureModel())

                //打印机配置
                hasPrinterAuto.postValue(SP.getBoolean(K_PRINTER_AUTO, v_printer_auto))

                //音响配置
                soundChannel = SP.getInt(K_SOUND_CHANNEL, v_sound_channel)
                soundAuto.postValue(SP.getBoolean(K_SOUND_AUTO, v_sound_auto))
                soundVolume.postValue(SP.getInt(K_SOUND_VOLUME, v_sound_volume))
                soundPre.postValue(SP.getBoolean(K_SOUND_PRE, v_sound_pre))
                soundStart.postValue(SP.getBoolean(K_SOUND_START, v_sound_start))
                soundEnd.postValue(SP.getBoolean(K_SOUND_END, v_sound_end))
                studentAddAuto.postValue(SP.getBoolean(K_ADD_STUDENT_AUTO, v_add_student_auto))
            }
            updateDialogLoading(false)
        }
    }

    private fun saveKeyValue() {


        SP.setInt(K_UPLOAD_MODEL, modelPosition)
        SP.setBoolean(K_IS_SUPER_MANAGER, isSuper.value!!)
        SP.setString(K_DEVICE_NAME, deviceNum.value!!)

        val baud = baudStr.value.toString().trim().toIntOrNull() ?: v_deviceBaud
        SP.setInt(K_DEVICE_BAUD, baud)
        SP.setBoolean(K_MODULE_CHECK_IN, hasCheckIn.value!!)
        SP.setBoolean(K_MODULE_SIGN_IN, hasSignIn.value!!)
        SP.setBoolean(K_MODULE_RESULT_CONFIRM, hasResultConfirm.value!!)
        SP.setBoolean(K_MODULE_DATA_SELECT, hasDataSelect.value!!)
        SP.setInt(K_CHECK_IN_MODE, inspectModel.value?.type ?: 0)
        SP.setInt(K_SIGN_IN_MODE, signInModel.value?.type ?: 0)
        SP.setInt(K_SCORE_QUERY_MODEL, queryModel.value?.type ?: 0)
        SP.setInt(K_SCORE_SURE_MODEL, sureModel.value?.type ?: 0)

        SP.setBoolean(K_PRINTER_AUTO, hasPrinterAuto.value!!)

        SP.setInt(K_SOUND_CHANNEL, soundChannel)
        SP.setBoolean(K_SOUND_AUTO, soundAuto.value!!)
        SP.setInt(K_SOUND_VOLUME, soundVolume.value!!)
        SP.setBoolean(K_SOUND_PRE, soundPre.value!!)
        SP.setBoolean(K_SOUND_START, soundStart.value!!)
        SP.setBoolean(K_SOUND_END, soundEnd.value!!)

        SP.setBoolean(K_ADD_STUDENT_AUTO, studentAddAuto.value!!)
    }

    fun save() {
        val server = serverAddress.value!!.trim()
        if (TextUtils.isEmpty(server)) {
            HttpManager.clearBaseUrl()
        } else {
            if (!HttpManager.isEffectiveServer(server)) {
                ToastUtils.showMyToast(R.string.sys_server_not_effective, Toast.LENGTH_SHORT)
                return
            }
            HttpManager.modifyBaseUrl(server)
        }
        SP.setString(K_SERVER_ADDRESS, server)
        launch {
            withContext(Dispatchers.Default) {
                saveKeyValue()
            }
            R.string.saveSuccess.showToast()
            finish()
        }
    }

    fun selectUploadModel(position: Int) {
        if (modelPosition == position) return
        modelPosition = position
        uploadModel.value = uploadModels.getOrNull(position)
    }

    fun selectCheckInModel(position: Int) {
        inspectModel.value = VerifyManager.inspectModels()[position]
    }

    fun selectSignInModel(position: Int) {
        signInModel.value = VerifyManager.signInModels()[position]
    }

    fun selectScoreQueryModel(position: Int) {
        queryModel.value = VerifyManager.queryModels()[position]
    }

    fun selectScoreSureModel(position: Int) {
        sureModel.value = VerifyManager.sureModels()[position]
    }

    fun selectExamArea(position: Int) {
        if (ProjectManager.selectExamArea(position)) {
            examAreaId.value = ProjectManager.currentExamArea?.examAreaCode
            examRoomId.value = null
        }
    }

    fun selectExamSite(position: Int) {
        if (ProjectManager.selectExamSite(position)) {
            examRoomId.value = ProjectManager.currentExamSite?.examSiteCode
        }
    }

    fun importsProjectOver(isSuccess: Boolean) {
        examPlanId.value = ProjectManager.examPlan?.planCode
        examAreaId.value = ProjectManager.currentExamArea?.examAreaCode
        examRoomId.value = ProjectManager.currentExamSite?.examSiteCode
    }

    //下载压缩包
    val zipAddress = MutableLiveData<ZipAddress>()
    fun zipInfo(planId: String) {
        if (!HttpManager.hasInitServer()) {
            ToastUtils.showMyToast(R.string.sys_server_none, Toast.LENGTH_SHORT)
            return
        }
        val api = HttpManager.getService(DownloadApi::class.java) ?: return
        launch {
            api.zip(planId)
                .catch { updateDialogLoading(false) }
                .onStart { updateDialogLoading(true) }
                .onCompletion { updateDialogLoading(false) }
                .collect {
                    if (it.isSuccess()) {
                        zipAddress.value = it.data!!
                    } else {
                        it.msg?.apply { ToastUtils.showMyToast(this, Toast.LENGTH_SHORT) }
                    }
                }
        }
    }

    //上传日志
    fun uploadLog() {
        if (!HttpManager.hasInitServer()) {
            ToastUtils.showMyToast(R.string.sys_server_none, Toast.LENGTH_SHORT)
            return
        }
        if (!isNetworkConnected(true)) return
        val logFile = File(FileUtils.getCacheDir(), BaseApp.CRASH_REPORTER)
        if (!logFile.exists() || !logFile.isFile) {
            ToastUtils.showMyToast(R.string.sys_log_none, Toast.LENGTH_SHORT)
            return
        }
        val api = HttpManager.getService(UploadApi::class.java) ?: return
        launch {
            val body = RequestBody.create(MediaType.parse("text/plain"), logFile)
            val part = MultipartBody.Part.createFormData("file", logFile.name, body)
            val logDate = DateUtils.format2(logFile.lastModified())
            api.upload(part).filter { it.isSuccess() }.flatMapConcat {
                val gson = "{\"createTime\":\"$logDate\", \"errorFile\":\"${it.data}\"}"
                LogUtils.i("logErr = $gson")
                api.uploadLog(gson.toJsonRequestBody())
            }.catch { updateDialogLoading(false) }
                .onStart { updateDialogLoading(true) }
                .onCompletion { updateDialogLoading(false) }
                .collect {
                    if (it.success()) {
                        //上传成功
                        ToastUtils.showMyToast(R.string.sys_upload_success)
                        logFile.delete()
                    } else {
                        it.msg?.apply { ToastUtils.showMyToast(this, Toast.LENGTH_SHORT) }
                    }
                }
        }
    }
}